package com.lancabbage.gorgeous.utils.doc;

import com.lancabbage.gorgeous.enums.ApiTypeEnum;
import com.lancabbage.gorgeous.enums.ParamModeEnum;
import com.thoughtworks.qdox.model.DocletTag;
import com.thoughtworks.qdox.model.JavaAnnotation;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class AnnotationUtils {
    /**
     * controller 注解
     */
    private static final List<String> controllerAnnotation = Arrays.asList("RestController", "Controller");

    /**
     * 参数描述取值方式
     */
    private List<String> parmTag;

    /**
     * 判断是否controller
     *
     * @param annotations 注解
     * @return 是否 path
     */
    public AnnotationRes isController(List<JavaAnnotation> annotations) {
        AnnotationRes res = new AnnotationRes();
        if (CollectionUtils.isEmpty(annotations)) {
            return res;
        }
        for (JavaAnnotation annotation : annotations) {
            //注解名称
            String name = annotation.getType().getName();
            if (controllerAnnotation.contains(name)) {
                res.isController = true;
                res.mode = "RestController".equals(name) ? 2 : 1;
            }
            //获取注解
            if (isMapping(name) != -1) {
                res.path = getMappingValue(annotation);
            }
        }

        return res;
    }

    /**
     * 判断是否controller
     *
     * @param annotations 注解
     * @return 是否 path
     */
    public AnnotationRes isApi(List<JavaAnnotation> annotations) {
        AnnotationRes res = new AnnotationRes();
        if (annotations == null || annotations.size() == 0) {
            return res;
        }
        //读取注解
        for (JavaAnnotation annotation : annotations) {
            String name = annotation.getType().getName();
            int isMapping = isMapping(name);
            if (isMapping != -1) {
                res.apiType = isMapping;
                res.path = getMappingValue(annotation);
                res.mode = "ResponseBody".equals(name) ? 2 : 1;
            }

        }
        return res;
    }

    /**
     * 判断注解是否mapping
     *
     * @param name 注解名称
     * @return 是否
     */
    private int isMapping(String name) {
        for (ApiTypeEnum type : ApiTypeEnum.values()) {
            if (type.getType().equals(name)) {
                return type.getCode();
            }
        }
        return -1;
    }

    /**
     * 获取mapping 路径
     *
     * @param annotation 注释
     * @return 路径
     */
    private String getMappingValue(JavaAnnotation annotation) {
        Map<String, Object> elementValuePairs = annotation.getNamedParameterMap();
        for (String name : elementValuePairs.keySet()) {
            if ("value".equals(name)) {
                String s = v(elementValuePairs.get(name).toString());
                if (!s.startsWith("/")) {
                    s = "/" + s;
                }
                if (s.endsWith("/")) {
                    s = s.substring(0, s.length() - 1);
                }
                return s;
            }
        }
        return "";
    }

    /**
     * 获取tag描述
     *
     * @param tags 方法注解上的 @param jobGroup    * @return
     * @return 描述
     */
    public String getTagDesc(List<DocletTag> tags) {
        if (CollectionUtils.isEmpty(tags)) {
            return null;
        }
        for (DocletTag tag : tags) {
            if (parmTag.contains(tag.getName()) || parmTag.contains("@" + tag.getName())) {
                return tag.getValue();
            }
        }
        return null;
    }

    /**
     * 参数注释信息
     *
     * @param tags 注释上的tag: @param @return
     * @return map
     */
    public Map<String, String> getParamMap(List<DocletTag> tags) {
        Map<String, String> map = new HashMap<>();
        if (CollectionUtils.isEmpty(tags)) {
            return map;
        }
        for (DocletTag tag : tags) {
            if (parmTag.contains(tag.getName()) || parmTag.contains("@" + tag.getName())) {
                if (tag.getParameters().isEmpty()) {
                    continue;
                }
                String key = tag.getParameters().get(0);
                String value = String.join(" ", tag.getParameters().subList(1, tag.getParameters().size()));
                map.put(key, value);
            }
        }
        return map;
    }

    /**
     * 获取参数名称
     *
     * @param annotation 注释
     * @return 名称
     */
    public String getParamValue(JavaAnnotation annotation, List<String> field) {
        Map<String, Object> elementValuePairs = annotation.getNamedParameterMap();
        for (String name : elementValuePairs.keySet()) {
            if (field.contains(name)) {
                //todo JavaAnnotation
                Object value = elementValuePairs.get(name);
                return v(value.toString());
            }
        }
        return "";
    }

    /**
     * 判断注解是否mapping
     *
     * @param name 注解名称
     * @return 是否
     */
    public int getParamMode(String name) {
        for (ParamModeEnum type : ParamModeEnum.values()) {
            if (type.getType().equals(name)) {
                return type.getCode();
            }
        }
        return -1;
    }

    /**
     * 获取注解描述
     *
     * @param annotations 注解
     * @return 是否
     */
    public String getAnnotationDesc(List<JavaAnnotation> annotations) {
        for (JavaAnnotation annotation : annotations) {
            String name1 = annotation.getType().getName();
            List<String> collect = this.parmTag.stream().filter(i -> i.contains(name1)).collect(Collectors.toList());
            if (!collect.isEmpty()) {
                String paramValue = getParamValue(annotation, collect.stream()
                        .map(i -> i.substring(i.indexOf("(") + 1, i.indexOf(")")))
                        .collect(Collectors.toList())
                );
                if (StringUtils.hasLength(paramValue)) {
                    return paramValue;
                }
            }

        }
        return "";
    }


    public void setParmTag(List<String> parmTag) {
        this.parmTag = parmTag;
    }

    private String v(String v) {
        return v.replaceAll("\"", "");
    }
}
